﻿using System;
using System.Diagnostics;

namespace Tables
{
	[Serializable]
	class HTable : IDisposable
	{
		public HTable ()
            : this (sizeHTable)
		{
		}

		public HTable (int size)
		{
			_aList = new List[size];
			init ();
		}
		/// <summary>
		/// Returns a short list of possible matches
		/// </summary>
		/// <param name="str"></param>
		/// <returns></returns>
		public List Find (string str)
		{
			return Find (str, str.Length);
		}
		/// <summary>
		/// Returns a short list of matches
		/// </summary>
		/// <param name="str"></param>
		/// <param name="len"></param>
		/// <returns></returns>
		public List Find (string str, int len)
		{
			int i = _Hash (str);
			return _aList [i];
		}
		/// <summary>
		/// Adds another string mapping
		/// </summary>
		/// <param name="str"></param>
		/// <param name="id"></param>
		public void Add (string str, int id)
		{
			int i = _Hash (str);
			_aList [i].Add (id);
		}

		public void Dispose ()
		{
			Dispose (true);
			GC.SuppressFinalize (this);
		}

		protected virtual void Dispose (bool disposing)
		{
			if (!_disposed) {
				if (disposing) {
					//disposed managed resource
					_aList = null;
				}
				// release unmanaged resource
			}
			_disposed = true;

			// if available, call to base class
			// base.Dispose(disposing);
		}

		private bool _disposed = false;
		private const int sizeHTable = 127; // 127 = 2^7 - 1
		private List[] _aList;

		private int _Hash(string str)
		{
			// implentation of the shift-and-add algorithm,
			// one of the best string randomizers
			Debug.Assert(str.Length != 0 && str [0] != null);
			UInt32 h = (UInt32)str [0];
			for (int i = 1; i < str.Length; ++i) {
				h = (h << 4) + (UInt32)str [i];
			}
			Debug.Assert (h >= 0);
			return (int)h % sizeHTable;
		}

		private void init ()
		{
			for (int i = 0;i < _aList.Length;++i) {
				_aList [i] = new List ();
			}
		}

	}
}
